using System;
using System.Collections;
using System.Data;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;
using Helper = PHSRAG.WebControls.Helper;

namespace PHSRAG.Insight21.Purchasing
{
    /// <summary> 
    /// The UserOrderDetails page supports viewing, adding, editing and deleting
    /// a user order and its associated line items to which a user has access to.
    /// </summary>
    /// <remarks>
    /// The user orders are of five types which are:
    /// <bullet>
    /// Purchase Order
    /// Travel Voucher
    /// Cheque Request
    /// Journal Entry
    /// Petty Cash
    /// </bullet>
    /// This page supports viewing and transacting on all the types of user order.
    /// It also supports converting an user oder to other type and sorting the line
    /// items based on user supplied criteria.
    /// </remarks> 
    public partial class UserOrderDetails : NoCachePage
    {
        #region Constants		

        private const string AccountNumberValidatorID = "accountNumberValidator";
        private const string CurrentOrderTypeKey = "CurrentOrderTypeKey_dca253fc-82ef-47cb-8553-bace40097f94";
        private const decimal DefaultAmount = 0;
        private const string DefaultCalendarPromptValue = "-- Select --";
        private const int DefaultOrderId = 0;
        private const string EmptyDistributionCountKey = "EmptyDistributionCountKey_dca253fc-82ef-47cb-8553-bace40097f94";
        private const string FundNumberValidatorID = "fundNumberValidator";
        private const int MaximumEmptyDistributions = 5;
        private const string OrderIDKey = "OrderIDKey_dca253fc-82ef-47cb-8553-bace40097f94";
        private const string OrderTypeTableIdColumn = "Id";
        private const string OrderTypeTableNameColumn = "Name";
        private const string PreviousURLKey = "PreviousURLKey_dca253fc-82ef-47cb-8553-bace40097f94";
        private const string UserOrdersVersionKey = "userOrdersVersionKey_dca253fc-82ef-47cb-8553-bace40097f94";

        #endregion

        #region Enumerations (Private)

        // Enumerates the columns in the Line Items Data Grid.
        // It has to be in sync with the columns and their order 
        // in lineItemsDataGrid.
        private enum DataGridColumnIndex
        {
            AccountNumber,
            FundNumber,
            Amount,
            RequestorName,
            Comment,
            Actions
        }

        #endregion

        #region Instance Variables (Private)		

        private bool allowDeleteDistributions;
        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;
        private ICachePolicy viewStatePolicy;
        // the value of this variable must be true, for the
        // delete button to be visible for line item.

        #endregion

        #region Private Properties

        /// <summary>
        /// Gets and sets the order type selected by the user. Uses the page cache policy for 
        /// storing the value. Returns integer value for Purchase Order as CurrentOrderType 
        /// if the value fetched from the pagecache policy is null. 
        /// </summary>
        private int CurrentOrderType
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable;
                return (h == null || h[CurrentOrderTypeKey] == null) ?
                                                                         (int) UserOrderUtility.UserOrderType.PurchaseOrder : (int) h[CurrentOrderTypeKey];
            }

            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable ?? new Hashtable();
                h[CurrentOrderTypeKey] = value;
                pageCachePolicy.Cache(Keys.UserOrderDetailsPageKey, h);
            }
        }

        /// <summary>
        /// Gets the UserOrder object with its data loaded.
        /// This property get the UserOrder object from the cache. It checks if the object
        /// is null or the orderid on the object is different than the current order id, if yes it
        /// checks the orderId, if its more than zero it restores the user order, else it instantiates the
        /// UserOrder oject of the specified type, creates its header table and adds a row to it.
        /// Then it caches and returns the user order object.
        /// </summary>
        private UserOrder UserOrderInstance
        {
            get
            {
                UserOrder userOrder = cachePolicy.
                    GetCachedObject(UserOrder.CacheKey) as UserOrder;
                int orderID = OrderID;
                if (userOrder == null || !userOrder.OrderID.Equals(orderID))
                {
                    if (orderID > DefaultOrderId)
                    {
                        userOrder = UserOrderUtility.LoadUserOrder(orderID, cachePolicy);
                    }
                    else
                    {
                        userOrder = UserOrderUtility.CreateUserOrder((UserOrderUtility.UserOrderType) CurrentOrderType, cachePolicy);
                        userOrder.CreateHeaderTableAndAddRow();
                    }
                    userOrder.Cache();
                }
                return userOrder;
            }
        }

        /// <summary>
        /// Gets and sets the order id passed by the summary page. Uses the page cache policy for 
        /// storing the value. Returns integer value for DefaultOrderId(0) as OrderID 
        /// if the value fetched from the pagecache policy is null. 
        /// </summary>
        private int OrderID
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable;
                return (h == null || h[OrderIDKey] == null) ? DefaultOrderId : (int) h[OrderIDKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable ?? new Hashtable();
                h[OrderIDKey] = value;
                pageCachePolicy.Cache(Keys.UserOrderDetailsPageKey, h);
            }
        }

        /// <summary>
        /// Gets and sets the URL of the page user navigated from. Uses the view state policy for 
        /// storing the value as it not required to be prserverd during inter page navigation.
        /// Returns an empty string if the value fetched from the pagecache policy is null.
        /// </summary>
        private string PreviousURL
        {
            get
            {
                Hashtable h = viewStatePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable;
                return (h == null || h[PreviousURLKey] == null) ? string.Empty : (string) h[PreviousURLKey];
            }
            set
            {
                Hashtable h = viewStatePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable ?? new Hashtable();
                h[PreviousURLKey] = value;
                viewStatePolicy.Cache(Keys.UserOrderDetailsPageKey, h);
            }
        }

        /// <summary>
        /// Get and sets the property indicating the empty distribution added in the line item datagrid.
        /// Uses the view state policy for storing the value as it not required to be prserverd during 
        /// inter page navigation.Returns zero if the value fetched from the pagecache policy is null. 
        /// </summary>
        private int EmptyDistributionCount
        {
            get
            {
                Hashtable h = viewStatePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable;
                return (h == null || h[EmptyDistributionCountKey] == null) ? 0 : Convert.ToInt32(h[EmptyDistributionCountKey]);
            }

            set
            {
                Hashtable h = viewStatePolicy.GetCachedObject(Keys.UserOrderDetailsPageKey) as Hashtable ?? new Hashtable();
                h[EmptyDistributionCountKey] = value;
                viewStatePolicy.Cache(Keys.UserOrderDetailsPageKey, h);
            }
        }

        /// <summary>
        ///	Increments user order version number used to determine whether user orders have been added/edited/deleted 
        ///	so that pages, such as Budget overview, that report on them can reload themselves.
        /// </summary>
        private int UserOrdersVersion
        {
            get
            {
                object version = pageCachePolicy.GetCachedObject(Keys.UserOrdersVersionKey);
                return version == null ? 0 : (int) version;
            }
            set { pageCachePolicy.Cache(Keys.UserOrdersVersionKey, value); }
        }

        #endregion

        #region Event Handlers

        #region PageLoad

        /// <summary>
        /// Handler for the event raised when the page loads. When the page is loaded for the
        /// first time, the existing(if) user order object is removed from the cache, breadcrumb
        /// is intialized and if there is any order id passed from the parent page it is retrieved
        /// and the user order instance is loaded. If no order id is passed, new user order is loaded.
        /// The url of the parent page is stored in viewstate, so that the user is naviagted back  to 
        /// the page he cam from after successful completion of save, cancel and delete operation . 
        /// If the user order is new the deleteUserOrder is not displayed. Its checked if the logged in user
        /// has rights to manage user order, if not the controls to manage user order is not displayed.
        /// Attributes are added to various controls on this page and dropdownlist displaying order types,
        /// header texboxes displaying order header information, the datagrid displaying line items 
        /// for the user order are loaded with data.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnPageLoad(object sender, EventArgs e)
        {
            annunciator.Message = string.Empty;
            annunciator.Title = string.Empty;
            if (!IsPostBack)
            {
                string key = UserOrder.CacheKey;
                if (cachePolicy.GetCachedObject(key) != null)
                {
                    cachePolicy.UnCache(key);
                }

                breadCrumb.Add(@"User Order Details", Settings.GetKeyValue
                    (@"SubNavigation.PurchasingDetails.UserOrderDetailsURL", string.Empty),
                    Settings.GetKeyValue(@"BreadCrumb.DetailPageLevel",
                        Constants.DefaultDetailPageLevelValue));

                int orderID = DefaultOrderId;
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                if (h != null)
                {
                    orderID = (h[Keys.UserOrderIdKey] == null) ? DefaultOrderId : (int) h[Keys.UserOrderIdKey];
                    h.Remove(Keys.UserOrderIdKey);
                }

                OrderID = orderID;
                PreviousURL = Request.UrlReferrer.LocalPath;

                UserOrder userOrder = UserOrderInstance;

                if (orderID.Equals(DefaultOrderId))
                {
                    deleteUserOrder.Visible = false;
                }

                CheckForManageUserOrderRights();

                AddAttributes();
                LoadUserOrderTypeList();
                DisplayHeaderItems(userOrder);
                DisplayLineItems(userOrder.LineItems);
            }

            purchasingSubModuleNavigation.SelectedSummaryLink = PurchasingSubNavigation.UserOrderSummaryCommand;
        }

        #endregion

        #region Add Distribution Event

        /// <summary>
        /// Adds a new line item to the lineitems collection. It checks
        /// for the number of empty distributions and if that is equal to
        /// five(zero based index), it disables the add distribution button.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnAddDistribution(object sender, ImageClickEventArgs e)
        {
            // ensure the order number textbox is not validated at this point
            orderNumberValidator.IsValid = true;

            try
            {
                UserOrder userOrder = UserOrderInstance;
                UserOrderLineItems lineItems = userOrder.LineItems;
                LoadLineItem(userOrder.OrderID, lineItems);
                lineItems.CreateLineItem();
                DisplayLineItems(lineItems);

                int emptyDistributionCount = EmptyDistributionCount;
                emptyDistributionCount++;
                EmptyDistributionCount = emptyDistributionCount;
                if (emptyDistributionCount == MaximumEmptyDistributions)
                {
                    addDistribution.Enabled = false;
                    addDistribution.ToolTip = @"At a time, there cannot be more 
						than five empty line items.";
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = String.Format("{0} Error in adding distribution item.",
                    ExceptionReport.GetExceptionInfo(ex, false));
            }
        }

        #endregion

        #region Header Events

        /// <summary>
        /// Handler for the event when deleteUserOrder button on the page is clicked.
        /// On successful deletion of the user order the user is naviagted back to 
        /// the page he from.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnDeleteUserOrder(object sender, ImageClickEventArgs e)
        {
            try
            {
                UserOrderInstance.DeleteUserOrder(DataAccess.GetConnectionString());

                // increment the user order version number used to determine whether user orders have been added/edited/deleted 
                // so that pages, such as Budget overview, that report on them can reload themselves.
                ++UserOrdersVersion;

                NavigateBack();
            }
            catch (Exception ex)
            {
                annunciator.Message = String.Format("{0} Error in deleting user order.",
                    ExceptionReport.GetExceptionInfo(ex, false));
            }
        }

        /// <summary>
        /// Handler for the event when cancel button on the page is clicked.
        /// On click of this button the user is naviagted back to the page he
        /// from.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnCancel(object sender, ImageClickEventArgs e)
        {
            try
            {
                NavigateBack();
            }
            catch (Exception ex)
            {
                annunciator.Message = String.Format("{0} Error in executing cancel operation.",
                    ExceptionReport.GetExceptionInfo(ex, false));
            }
        }

        /// <summary>
        /// Handler for event when save button is clicked. It checks if the
        /// order type selected is different then the order type of the current user order
        /// object, then it calls a method to convert the order type. Then it loads the
        /// order header and line items and calls the save method on it. It updates the
        /// order id after save and makes the visible property of the deleteuserorder
        /// button and addDistribution button to true. If the operation is succesful
        /// the user is navigated back to the page he came from.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnSave(object sender, ImageClickEventArgs e)
        {
            if (ValidateUserInput())
            {
                try
                {
                    CurrentOrderType = Convert.ToInt32(orderTypeList.SelectedValue);

                    UserOrder userOrder = UserOrderInstance;
                    if (!userOrder.OrderTypeID.Equals(CurrentOrderType))
                    {
                        userOrder.UnCache();
                        userOrder = UserOrderUtility.ConvertUserOrder(userOrder, (UserOrderUtility.UserOrderType) CurrentOrderType,
                            cachePolicy);
                        userOrder.Cache();
                    }
                    LoadOrderHeader(userOrder);
                    LoadLineItem(userOrder.OrderID, userOrder.LineItems);
                    userOrder.Save(DataAccess.GetConnectionString());

                    // increment user order version to show that there has been a change
                    ++UserOrdersVersion;

                    NavigateBack();
                }
                catch (Exception ex)
                {
                    annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
                }
            }
        }

        #endregion

        #region LineItems DataGrid Events

        /// <summary>
        /// Handler for the event when delete button on the line item is clicked.
        /// It reduces the count of empty distributions if a newly added distribution
        /// is being deleted. It loads the lineitems collection with whatever changes 
        /// made by the user and deletes the line item on which delete button has been 
        /// clicked.
        /// </summary>
        /// <param name="source">Control which raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnLineItemsDataGridDeleteCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                UserOrder userOrder = UserOrderInstance;
                UserOrderLineItems lineItems = userOrder.LineItems;
                int itemIndex = e.Item.ItemIndex;
                if (lineItems[itemIndex].CurrentState == DataRowState.Added)
                {
                    int emptyDistributionCount = EmptyDistributionCount;
                    emptyDistributionCount--;
                    EmptyDistributionCount = emptyDistributionCount;

                    if (emptyDistributionCount < MaximumEmptyDistributions)
                    {
                        addDistribution.Enabled = true;
                        addDistribution.ToolTip = string.Empty;
                    }
                }
                LoadLineItem(userOrder.OrderID, lineItems);
                lineItems.DeleteLineItem(itemIndex);
                DisplayLineItems(lineItems);
            }
            catch (Exception ex)
            {
                annunciator.Message = String.Format("{0} Error in deleting line item.",
                    ExceptionReport.GetExceptionInfo(ex, false));
            }
        }

        /// <summary>
        /// Handler for event raised when an item is data bound to LineItemsDataGrid.
        /// While binding data check if the amount field has negative values then assign a 
        /// style for displaying negative values. Attributes to check if the values in the
        /// fields have changed is added to all the textboxes.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnLineItemsDataGridItemDataBound(object sender, DataGridItemEventArgs e)
        {
            DataGridItem item = e.Item;
            if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
            {
                UserOrderLineItem lineItem = (UserOrderLineItem) item.DataItem;

                TextBox accountNumber = (TextBox) item.FindControl("accountNumber");
                accountNumber.Text = lineItem.AccountNumber;
                accountNumber.Attributes.Add("onchange", "javascript:SetLineDirty();");

                TextBox fundNumber = (TextBox) item.FindControl("fundNumber");
                fundNumber.Text = lineItem.FundNumber;
                fundNumber.Attributes.Add("onchange", "javascript:SetLineDirty();");

                TextBox amount = (TextBox) item.FindControl("amount");
                amount.Text = lineItem.Amount.ToString("c", Helper.ChooseDecimals(2));
                if (lineItem.Amount < 0)
                {
                    amount.CssClass = "FlatTextNegativeCurrency";
                }
                amount.Attributes.Add("onchange", "javascript:SetLineDirty();");

                TextBox requestor = (TextBox) item.FindControl("requestor");
                requestor.Text = lineItem.RequestorName;
                requestor.Attributes.Add("onchange", "javascript:SetLineDirty();");

                TextBox distributionComment = (TextBox) item.FindControl("distributionComment");
                distributionComment.Text = lineItem.Comment;
                distributionComment.Attributes.Add("onchange", "javascript:SetLineDirty();");

                if (allowDeleteDistributions)
                {
                    ImageButton deleteDistribution = (ImageButton) item.FindControl("deleteDistribution");
                    deleteDistribution.Visible = true;
                    deleteDistribution.Attributes.Add("onClick", "javascript:return ConfirmDeleteLineItem();");
                    deleteDistribution.ImageUrl = (item.ItemType == ListItemType.AlternatingItem) 
                        ? "../Images/b_delete.gif" 
                        : "../Images/b_deleteongray.gif";
                }
            }
            else if (item.ItemType == ListItemType.Footer)
            {
                Label total = (Label) item.FindControl("total");
                if (total != null)
                {
                    decimal totalAmount = UserOrderInstance.TotalAmount;
                    total.Text = totalAmount.ToString("c", Helper.ChooseDecimals(2));
                    if (totalAmount < 0)
                    {
                        total.CssClass = Constants.DeficitStyle;
                    }
                }
            }
        }

        #endregion

        #region Header

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            purchasingSubModuleNavigation.Reset();
        }

        #endregion

        #endregion

        #region Private Methods

        /// <summary>
        /// This method sets the display of controls displaying the user order
        /// header information. It gets the data common to all user order from
        /// the user order object and then checks its underlying type, and sets the
        /// displays text to controls as per the user order type.
        /// </summary>
        /// <param name="userOrder">current user order object</param>
        private void DisplayHeaderItems(UserOrder userOrder)
        {
            try
            {
                orderTypeList.SelectedIndex = userOrder.OrderTypeID - 1;
                orderNumber.Text = userOrder.OrderNumber.Trim();
                if (userOrder.TransactionDate != string.Empty)
                {
                    transactionDate.Prompt = userOrder.TransactionDate.Trim();
                }
                invoiceNumber.Text = userOrder.InvoiceNumber.Trim();
                if (userOrder.InvoiceDate != string.Empty)
                {
                    invoiceDate.Prompt = userOrder.InvoiceDate.Trim();
                }
                headerComment.Text = userOrder.Comment.Trim();

                if (userOrder is PurchaseOrder)
                {
                    PurchaseOrder purchaseOrder = (PurchaseOrder) userOrder;
                    vendorName.Text = purchaseOrder.VendorName.Trim();
                    vendorNumber.Text = purchaseOrder.VendorNumber.Trim();
                    requistionNumber.Text = purchaseOrder.RequisitionNumber.Trim();
                    invoiceNumber.Text = purchaseOrder.InvoiceNumber.Trim();
                    if (purchaseOrder.InvoiceDate != string.Empty)
                    {
                        invoiceDate.Prompt = purchaseOrder.InvoiceDate.Trim();
                    }
                }
                else if (userOrder is Voucher)
                {
                    Voucher voucher = (Voucher) userOrder;
                    vendorName.Text = voucher.VendorName.Trim();
                    vendorNumber.Text = voucher.VendorNumber.Trim();
                    invoiceNumber.Text = voucher.InvoiceNumber.Trim();
                    if (voucher.InvoiceDate != string.Empty)
                    {
                        invoiceDate.Prompt = voucher.InvoiceDate.Trim();
                    }
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = String.Format("{0} Error in displaying order header.",
                    ExceptionReport.GetExceptionInfo(ex, false));
            }
        }

        /// <summary>
        /// This method sets and binds the datasource of the datagrid displaying
        /// lineitems. It checks if the line item count is more than one, if yes
        /// allowDeleteDistributions is set to true else false. This is done to
        /// ensure that the delete button is not visible if there is only one line item.
        /// </summary>
        /// <param name="lineItems">lineitems related to the user order object</param>
        private void DisplayLineItems(UserOrderLineItems lineItems)
        {
            try
            {
                allowDeleteDistributions = lineItems.Count > 1 ? true : false;
                lineItemsDataGrid.DataSource = lineItems;
                lineItemsDataGrid.DataBind();
            }
            catch (Exception ex)
            {
                annunciator.Message = String.Format("{0} Error in displaying line items.",
                    ExceptionReport.GetExceptionInfo(ex, false));
            }
        }

        /// <summary>
        /// Load the specified user order object with the data entered by the user.
        /// This event assigns the property common to all user orders on the user order
        /// object and then determines the type of user order and assigns values to the
        /// properties specific to the user order type.
        /// The calendar prompt value needs to be retrieved and checked, because the
        /// user order may be an exisitng user order and date value of exisitng user order
        /// is displayed in the prompt and not in selection property of the calendar control.
        /// The selection property is readonly, and in case when the user does not change
        /// the date value in date controls, while updating, the display still has to be 
        /// carried to the database to be updated else empty values will be updated.
        /// </summary>
        /// <param name="userOrder">current user order object</param>
        private void LoadOrderHeader(UserOrder userOrder)
        {
            userOrder.OrderNumber = orderNumber.Text;
            userOrder.TransactionDate = (transactionDate.Selection.Equals(string.Empty)) ?
                                                                                             (transactionDate.Prompt.Equals(DefaultCalendarPromptValue) ? string.Empty : transactionDate.Prompt)
                : transactionDate.Selection;
            userOrder.Comment = headerComment.Text.Trim();
            userOrder.OrderTypeID = Convert.ToInt32(orderTypeList.SelectedValue);
            userOrder.InvoiceNumber = invoiceNumber.Text;
            userOrder.InvoiceDate = (invoiceDate.Selection.Equals(string.Empty)) ?
                                                                                     (invoiceDate.Prompt.Equals(DefaultCalendarPromptValue) ? string.Empty : invoiceDate.Prompt)
                : invoiceDate.Selection;


            if (userOrder is PurchaseOrder)
            {
                PurchaseOrder purchaseOrder = (PurchaseOrder) userOrder;
                purchaseOrder.VendorName = vendorName.Text;
                purchaseOrder.VendorNumber = vendorNumber.Text;
                purchaseOrder.RequisitionNumber = requistionNumber.Text;
                purchaseOrder.InvoiceNumber = invoiceNumber.Text;
                purchaseOrder.InvoiceDate = (invoiceDate.Selection.Equals(string.Empty)) ?
                                                                                             (invoiceDate.Prompt.Equals(DefaultCalendarPromptValue) ? string.Empty : invoiceDate.Prompt)
                    : invoiceDate.Selection;
            }
            else if (userOrder is Voucher)
            {
                Voucher voucher = (Voucher) userOrder;
                voucher.VendorName = vendorName.Text;
                voucher.VendorNumber = vendorNumber.Text;
                voucher.InvoiceNumber = invoiceNumber.Text;
                voucher.InvoiceDate = (invoiceDate.Selection.Equals(string.Empty)) ?
                                                                                       (invoiceDate.Prompt.Equals(DefaultCalendarPromptValue) ? string.Empty : invoiceDate.Prompt)
                    : invoiceDate.Selection;
            }
        }

        /// <summary>
        /// This method loads the data entered/modified by the user in the line item collection.
        /// While loading the amount the currency symbol and the brackets if present are removed.
        /// </summary>
        /// <param name="orderID">order id of the user order to which the line item belongs</param>
        /// <param name="userOrderLineItems">the lineitem which has to be loaded with data enterd by the user</param>		
        private void LoadLineItem(int orderID, UserOrderLineItems userOrderLineItems)
        {
            DataGridItemCollection lineItemsCollection = lineItemsDataGrid.Items;
            foreach (DataGridItem lineItem in lineItemsCollection)
            {
                UserOrderLineItem userOrderLineItem = userOrderLineItems[lineItem.ItemIndex];
                userOrderLineItem.OrderID = orderID;
                userOrderLineItem.AccountNumber = ((TextBox) lineItem.FindControl("accountNumber")).Text;
                userOrderLineItem.FundNumber = ((TextBox) lineItem.FindControl("fundNumber")).Text;

                string amountEntered = ((TextBox) lineItem.FindControl("amount")).Text.Replace
                    (CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol, string.Empty).
                    Replace("(", string.Empty).Replace(")", string.Empty);
                try
                {
                    userOrderLineItem.Amount = (amountEntered.Equals(string.Empty)
                        ? DefaultAmount : Convert.ToDecimal(amountEntered));
                }
                catch
                {
                    ((TextBox) lineItem.FindControl("amount")).CssClass = "Errors";
                    throw new Exception("Please correct the errors highlighted below");
                }

                userOrderLineItem.RequestorName = ((TextBox) lineItem.FindControl("requestor")).Text;
                userOrderLineItem.Comment = ((TextBox) lineItem.FindControl("distributionComment")).Text.Trim();
            }
        }

        /// <summary>
        /// Checks if the logged in user has rights to manage the user order. A bitwise and operation
        /// is performed on the modulerolebitmask of the logged in user and the bit value for manageuserorders
        /// to check if the user has the module role bit to manage user order. If the opeartion evalutes to zero
        /// (false) the visibility of controls to manage user order is set to false.
        /// </summary>
        private void CheckForManageUserOrderRights()
        {
            try
            {
                if ((((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask
                    & (int) ModuleRoleBit.ManageUserOrders) == 0)
                {
                    deleteUserOrder.Visible = false;
                    addDistribution.Visible = false;
                    save.Visible = false;
                    lineItemsDataGrid.Columns[(int) DataGridColumnIndex.Actions].Visible = false;
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Adds javascript funations as attributes to the server controls. These
        /// javascript functions will get fired on the client side when these server
        /// controls are clicked or if there is change in their state.
        /// </summary>
        private void AddAttributes()
        {
            orderTypeList.Attributes.Add("onchange", "javascript:DisplayHeaderColumns();");
            orderNumber.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            vendorName.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            invoiceNumber.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            transactionDate.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            requistionNumber.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            vendorNumber.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            invoiceDate.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            headerComment.Attributes.Add("onchange", "javascript:SetHeaderDirty();");
            deleteUserOrder.Attributes.Add("onClick", "javascript:return ConfirmDeleteUserOrder();");
            cancel.Attributes.Add("onClick", "javascript:return ConfirmLooseChanges();");
        }

        /// <summary>
        /// This method will load the dropdown list control with the
        /// list of user order types
        /// </summary>
        private void LoadUserOrderTypeList()
        {
            orderTypeList.DataSource = UserOrderHelper.GetOrderTypeTable();
            orderTypeList.DataTextField = OrderTypeTableNameColumn;
            orderTypeList.DataValueField = OrderTypeTableIdColumn;
            orderTypeList.DataBind();
        }

        /// <summary>
        /// Naviagtes back to the page the user came from.
        /// </summary>
        private void NavigateBack()
        {
            if (!PreviousURL.Equals(string.Empty))
            {
                Response.Redirect(PreviousURL);
            }
            else
            {
                throw new Exception(@"Error in navigating back to the previous page");
            }
        }

        /// <summary>
        /// Checks if the order number at the header, fund number and account number
        /// in all the line items are not empty.
        /// </summary>
        /// <returns>Return true if the user input in header and details is valid</returns>
        private bool ValidateUserInput()
        {
            bool allFundValid;
            bool orderNumberValid;
            bool allAcctValid = allFundValid = orderNumberValid = true;
            if (!orderNumberValidator.IsValid)
            {
                orderNumberValid = false;
                orderNumber.CssClass = "Errors";
            }
            else
            {
                orderNumber.CssClass = "FlatText";
            }

            DataGridItemCollection lineItemsCollection = lineItemsDataGrid.Items;

            for (int index = 0; index < lineItemsCollection.Count; index++)
            {
                allAcctValid = ((RequiredFieldValidator) lineItemsCollection[index].FindControl(AccountNumberValidatorID)).IsValid;
                ((TextBox) lineItemsCollection[index].FindControl("accountNumber")).CssClass = !allAcctValid ? "Errors" : "FlatText";

                allFundValid = ((RequiredFieldValidator) lineItemsCollection[index].FindControl(FundNumberValidatorID)).IsValid;
                ((TextBox) lineItemsCollection[index].FindControl("fundNumber")).CssClass = !allFundValid ? "Errors" : "FlatText";
            }

            return (allAcctValid && allFundValid && orderNumberValid);
        }

        #endregion

        #region Web Form Designer generated code

        protected override void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);

            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
            viewStatePolicy = new ViewStateCachePolicy(ViewState);
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.lineItemsDataGrid.DeleteCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnLineItemsDataGridDeleteCommand);
            this.lineItemsDataGrid.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnLineItemsDataGridItemDataBound);
            this.addDistribution.Click += new ImageClickEventHandler(OnAddDistribution);
            this.deleteUserOrder.Click += new ImageClickEventHandler(OnDeleteUserOrder);
            this.cancel.Click += new ImageClickEventHandler(this.OnCancel);
            this.save.Click += new ImageClickEventHandler(this.OnSave);
            this.Load += new System.EventHandler(this.OnPageLoad);
        }

        #endregion
    }
}